<template>
  <div class="sys-paramter-form-warpper">
    <div class="toolbar-warpper">
      <div v-if="!editStatus">
        <el-button type="success" @click="onEdit">编辑</el-button>
        <el-button @click="onRefresh">刷新</el-button>
      </div>
      <div v-else>
        <el-button type="primary" @click="onSave" :disabled="!hasChangeStatus">保存</el-button>
        <el-button type="danger" @click="onCancelEdit">撤销</el-button>
      </div>
    </div>
    <el-form ref="formRef" label-width="auto" :model="formData">
      <el-descriptions :column="1" border>
        <el-descriptions-item label-align="right" label-width="150px" v-for="(component, index) in componentList" :key="index">
          <template #label>
            <div :class="component.required ? 'required' : ''" v-text="component.label"></div>
          </template>
          <div v-if="editStatus === true">
            <el-form-item :prop="component.fieldCode" :rules="component.formItemProps?.rules">
              <render-component v-model="formData[component.fieldCode]" :component-name="component.componentName" :component-pros="component.props"></render-component>
            </el-form-item>
          </div>
          <div v-else style="margin: 12px 0">
            {{ formData[component.fieldCode] }}
          </div>
        </el-descriptions-item>
      </el-descriptions>
    </el-form>
  </div>
</template>
<script setup lang="ts">
import { getParameterComponentList, getParameterValueJson, save } from '@/api/sys/paramter';
import { ElMessageBox, type FormInstance } from 'element-plus';
import { ref, onBeforeMount, watch } from 'vue';
import RenderComponent from './render-component';

interface IParameterComponent {
  label: string;
  fieldCode: string;
  componentName: string;
  required: boolean;
  formItemProps: Record<string, unknown>;
  props: Record<string, unknown>;
}
defineOptions({
  name: 'SysParameterForm',
});
const props = defineProps({
  categoryCode: {
    type: String,
    required: true,
  },
});
const formRef = ref<FormInstance>();

const editStatus = ref<boolean>(false);

const componentList = ref<IParameterComponent[]>([]);

const hasChangeStatus = ref<boolean>(false);
const formData = ref<Record<string, object>>({});
onBeforeMount(async () => {
  await getComponentList();
  await getFormData();
});
const getComponentList = async () => {
  const { data } = await getParameterComponentList(props.categoryCode);
  componentList.value = data as unknown as IParameterComponent[];
};

const getFormData = async () => {
  const { data } = await getParameterValueJson(props.categoryCode);
  formData.value = data as unknown as Record<string, object>;
};

let oldFormData: Record<string, object> = {};
//编辑
const onEdit = () => {
  oldFormData = JSON.parse(JSON.stringify(formData.value));
  editStatus.value = true;
};

//取消编辑
const onCancelEdit = () => {
  if (hasChangeStatus.value) {
    ElMessageBox.confirm('数据已发送改变，确认放弃保存?', '询问', {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(() => {
      formData.value = oldFormData;
      editStatus.value = false;
      hasChangeStatus.value = false;
    });
  } else {
    formData.value = oldFormData;
    editStatus.value = false;
  }
};
//刷新
const onRefresh = () => {
  getFormData();
};
//保存
const onSave = () => {
  const data = getChangeData();
  save(data).then(() => {
    editStatus.value = false;
  });
};

const getChangeData = (): Record<string, object> => {
  const changeData: Record<string, object> = {};
  Object.keys(formData.value).forEach((key: string) => {
    if (formData.value[key] !== oldFormData[key]) {
      changeData[key] = formData.value[key];
    }
  });
  return changeData;
};

watch(
  formData,
  () => {
    if (JSON.stringify(formData.value) != JSON.stringify(oldFormData) && editStatus.value === true) {
      hasChangeStatus.value = true;
    } else {
      hasChangeStatus.value = false;
    }
  },
  { deep: true },
);
</script>
<style lang="scss" scoped>
.sys-paramter-form-warpper {
  width: 90%;
  margin: 0px auto;
}
.toolbar-warpper {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.required {
  &::before {
    content: '*';
    color: #ff4949;
    margin-right: 2px;
  }
}
</style>
